package org.kernely.security.ui.user.mgmt;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;

import org.kernely.security.dao.UserDAO;
import org.kernely.security.dao.UserDetailsDAO;
import org.kernely.security.persistence.Group;
import org.kernely.security.persistence.Role;
import org.kernely.security.persistence.User;
import org.kernely.security.persistence.UserDetails;
import org.kernely.security.ui.SecurityUIBundle;
import org.kernely.security.ui.group.mgmt.ManagementGroupEvent;
import org.kernely.ui.mvp.KernelyEvent;
import org.kernely.ui.mvp.KernelyEventReceiver;
import org.kernely.ui.mvp.KernelyPresenter;
import org.kernely.ui.utils.KernelyDialogWindow;
import org.kernely.ui.utils.KernelyNotification;
import org.osgi.service.event.Event;

import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.terminal.ExternalResource;
import com.vaadin.ui.Button;
import com.vaadin.ui.Layout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Window.Notification;


/**
 * Presenter for the management of users.
 */
@SuppressWarnings("serial")
public class UserManagementPresenter extends KernelyPresenter<UserManagementView> implements KernelyEventReceiver{

	/**
	 * Serial version ID
	 */
	private Window subwindow;
	private Button.ClickListener enableListener;
	private Button.ClickListener disableListener;
	private KernelyDialogWindow confirmWindow;

	/**
	 * @see org.kernely.core.service.IKernelyPresenter#bind()
	 */
	@Override
	public final void bind() {
		SecurityUIBundle.getEventBus().addListener(this);
		listUsers();

		// Add a listener to the table
		this.view.getTable().addListener(new Property.ValueChangeListener() {
			/**
			 * The method called when a user select an item in the table.
			 */
			@Override
			public void valueChange(ValueChangeEvent event) {
				toggleStateButtons();
			}
		});

		// Add a listener to the add button
		this.view.getbAddUser().addListener(new Button.ClickListener() {
			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				if(!SecurityUIBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().showNotification("Error", "You are not administrator!", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					displayAddEditUserWindow(false);
				}
			}
		});

		// Add a listener to the edit button
		this.view.getbEditUser().addListener(new Button.ClickListener() {
			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				if(!SecurityUIBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().showNotification("Error", "You are not administrator!", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					displayAddEditUserWindow(true);
				}
			}
		});

		// Create a listener for the click on the disable button.
		disableListener = new ClickListener() {

			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			@Override
			public void buttonClick(ClickEvent event) {
				if(!SecurityUIBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().showNotification("Error", "You are not administrator!", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					showEnableDisableWindow(false);
				}
			}
		};

		// Create a listener for the click on the enable button.
		enableListener = new ClickListener() {

			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			@Override
			public void buttonClick(ClickEvent event) {
				if(!SecurityUIBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().showNotification("Error", "You are not administrator!", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					showEnableDisableWindow(true);
				}
			}
		};
		
		this.view.getShowDisabledUser().addListener(new ValueChangeListener() {
			/**
			 * @see com.vaadin.data.Property.ValueChangeListener#valueChange(com.vaadin.data.Property.ValueChangeEvent)
			 */
		    public void valueChange(ValueChangeEvent event) {
		        listUsers();
		    }
		});
	}

	/**
	 * Change the state of the edit and enable/disable buttons.
	 * If nothing is selected in the table, disable the Edit and Enable/Disable buttons.
	 * If a line is selected, buttons are enabled.
	 */
	protected final void toggleStateButtons() {
		if (view.getTable().getValue() == null){
			view.getbEditUser().setEnabled(false);
			view.getStateButton().setEnabled(false);
			view.getStateButton().setCaption("Enable/Disable");
		} else {
			view.getbEditUser().setEnabled(true);
			view.getStateButton().setEnabled(true);

			//Change the text and the function of the Disable/Enable button
			UserDetailsDAO uddao = new UserDetailsDAO();
			User u = uddao.findUserDetails((Integer)view.getTable().getValue()).getUser();

			// If the user is enabled, the state button is a disable button.
			if (u.getEnabled() == 1){
				view.getStateButton().setCaption("Disable an user");
				// We remove all listeners...
				view.getStateButton().removeListener(disableListener);
				view.getStateButton().removeListener(enableListener);

				// And add the disable listener.
				view.getStateButton().addListener(disableListener);
			}
			// If the user is disabled, the state button is an enable button.
			else {
				view.getStateButton().setCaption("Enable an user");				
				// We remove all listeners...
				view.getStateButton().removeListener(disableListener);
				view.getStateButton().removeListener(enableListener);

				// And add the enable listener.
				view.getStateButton().addListener(enableListener);
			}
		}
	}

	/**
	 * Add all registered user into the table
	 */
	private void listUsers(){
		// Only administrators can view users'list
		if(SecurityUIBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR)){
			User currentUser = SecurityUIBundle.getSecurityService().getCurrentUser();

			// Reset the table
			view.getTable().removeAllItems();

			UserDetailsDAO uddao = new UserDetailsDAO();
			List<UserDetails> detail = uddao.getAllUserDetails();
			for(UserDetails ud : detail){
				// The current user will not be displayed
				if(ud.getUser().getId() != currentUser.getId()){

					// Is the user enabled ?
					String access = "";
					if(ud.getUser().getEnabled() == 1){
						access = "Yes";
					}
					else{
						access = "No";
					}

					// In which groups is the user ?
					String groups = "";
					List<Group> groupsList = new ArrayList<Group>(ud.getUser().getGroups());

					if (!groupsList.isEmpty()){
						// Create the string with comas
						for (Group group : groupsList){
							groups += group.getName() + ", ";
						}
						// Remove the last coma
						groups = groups.substring(0, groups.lastIndexOf(','));
					}


					// Fill the table
					if(ud.getUser().getEnabled() == 1 || (Boolean)this.view.getShowDisabledUser().getValue()){
						Object o = this.view.getTable().addItem(new Object[] {
								ud.getName(),
								ud.getFirstname(),
								ud.getMail(),
								groups,
								access}, ud.getId_user_detail());
						
						if(ud.getUser().getEnabled() == 0){
							this.view.getTable().setItemIcon(o,new ExternalResource("securityUIbundle/images/user_red.png"));
						}
						else{
							this.view.getTable().setItemIcon(o,new ExternalResource("securityUIbundle/images/user_green.png"));
						}
					}
				}
			}
			view.getTable().sort();
		}
	}

	/**
	 * Handle Kernely events : when meaningful events are received, we update the list.
	 */
	public final void handleKernelyEvent(KernelyEvent event) {
		if (event instanceof ManagementUserEvent){
			listUsers();
		}
		if (event instanceof ManagementGroupEvent){
			listUsers();
		}
	}

	/**
	 * Called when the presenter is unset from application : it must unregister from event bus.
	 */
	@Override
	public final void unset() {
		SecurityUIBundle.getEventBus().removeListener(this);
	}
	
	private void displayAddEditUserWindow(boolean editMode){
		UserManagementWindowPresenter umwp = null;
		UserManagementWindowView umwv;
		if (editMode){
			UserDetailsDAO uddao = UserDetailsDAO.getInstance();
			subwindow = new Window("Kernely - Edit an user ");
			umwp = new UserManagementWindowPresenter(uddao.findUserDetails((Integer)view.getTable().getValue()));
		} else {
			subwindow = new Window("Kernely - Add an user ");
			umwp = new UserManagementWindowPresenter();

		}
		subwindow.setModal(true);
		subwindow.setResizable(false);
		view.getWindow().addWindow(subwindow);
		subwindow.getContent().setSizeUndefined();
		umwv = new UserManagementWindowView();
		umwp.setView(umwv);
		subwindow.setContent((Layout)umwp.getView());
		subwindow.setIcon(new ExternalResource("securityUIbundle/images/user_basic.png"));
	}
	
	private void showEnableDisableWindow(boolean enable){
		final boolean en = enable;
		
		// Get the user
		UserDetailsDAO uddao = UserDetailsDAO.getInstance();
		UserDetails details = uddao.findUserDetails((Integer)view.getTable().getValue());
		
		// Confirm window
		if (enable){
			confirmWindow = new KernelyDialogWindow("Kernely - Enable user", "Do you really want to enable " + details.getFirstname() + " " + details.getName() + "?", KernelyDialogWindow.WARNING_ICON);			
		} else {
			confirmWindow = new KernelyDialogWindow("Kernely - Disable user", "Do you really want to disable " + details.getFirstname() + " " + details.getName() + "?", KernelyDialogWindow.WARNING_ICON);

		}
		confirmWindow.setConfirmButtonCaption("Yes");
		confirmWindow.setCancelButtonCaption("No");
		// Adding listeners on window's "confirm" buttons click
		confirmWindow.getConfirmButton().addListener(new Button.ClickListener() {
			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			@Override
			public void buttonClick(ClickEvent event) {
				enableUser(en);
			}
		});
		view.getWindow().addWindow(confirmWindow);
	}
	
	private void enableUser(boolean enabled){
		UserDetails details = UserDetailsDAO.getInstance().findUserDetails((Integer)view.getTable().getValue());
		User user = details.getUser();
		UserDAO udao = UserDAO.getInstance();
		String state = null;
		
		// Change user's state in the database
		if (enabled){
			user.setEnabled(1);
			state = "enabled";
		} else {
			user.setEnabled(0);
			state = "disabled";
		}

		udao.update(user);

		// We send an event to other bundles to notify them that an user has been modified.
		// Set the properties of the event
		Dictionary<String, Object> properties = new Hashtable<String,Object>();
		properties.put("title", SecurityUIBundle.EDIT_USER);
		properties.put("path" , this.getClass().getName()+"enableUser");
		properties.put("time", System.currentTimeMillis());
		properties.put("user", user);
		//Send event
		Event userEvent = new Event("org/kernely/security", properties);
		SecurityUIBundle.getEventAdminService().postEvent(userEvent);
		
		// Remove the confirm window
		view.getWindow().removeWindow(confirmWindow);

		//Inform the user
		view.getWindow().showNotification(new KernelyNotification("User " + details.getFirstname() + " " + details.getName() + " is now "+ state, KernelyNotification.INFO_ICON));

		//Refresh the table
		listUsers();

	}

}
